interface: ask for unicast responses by default
authorFelix Fietkau <[email protected]>
Wed, 28 May 2025 22:07:47 +0000 (00:07 +0200)
committerFelix Fietkau <[email protected]>
Wed, 28 May 2025 22:07:48 +0000 (00:07 +0200)
When able to bind the socket without REUSEPORT, unicast responses can
be received on the main port. Indicate that in outgoing questions in order
to reduce unnecessary multicast traffic.

Signed-off-by: Felix Fietkau <[email protected]>
dns.c
interface.c
interface.h

diff --git a/dns.c b/dns.c
index 7c24ddc8be4de9bbeefbaad87cc7e80d0c57d2bd..18210f177a11ef517952ee298eef1111dbe4f1a5 100644 (file)
--- a/dns.c
+++ b/dns.c
@@ -185,7 +185,7 @@ void dns_packet_send(struct interface *iface, struct sockaddr *to, bool query, i
 
        if (query) {
                if (multicast < 0)
-                       multicast = interface_multicast(iface);
+                       multicast = iface->need_multicast;
 
                for (i = 0; i < pkt_n_q; i++)
                        dns_question_set_multicast(pkt_q[i], multicast);
index 944666f1b0a058c6cd924751f9b477a0bf17de2a..e2f0ce9a4e1c2ea65199b419b851fc09a2d2e24d 100644 (file)
@@ -478,7 +478,7 @@ iface_update_cb(struct vlist_tree *tree, struct vlist_node *node_new,
                interface_start(if_new);
 }
 
-static int interface_init_socket(enum umdns_socket_type type)
+static int interface_init_socket(enum umdns_socket_type type, bool *mcast)
 {
        struct sockaddr_in6 local6 = {
                .sin6_family = AF_INET6
@@ -492,6 +492,7 @@ static int interface_init_socket(enum umdns_socket_type type)
        int no = 0;
        int fd;
        int af = (type & SOCKTYPE_BIT_IPV6) ? AF_INET6 : AF_INET;
+       bool reuseport = false;
 
        if (ufd[type].fd >= 0)
                return 0;
@@ -501,9 +502,6 @@ static int interface_init_socket(enum umdns_socket_type type)
                return -1;
 
        setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes));
-#ifdef SO_REUSEPORT
-       setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &yes, sizeof(yes));
-#endif
 
        switch (type) {
        case SOCK_UC_IPV4:
@@ -524,6 +522,7 @@ static int interface_init_socket(enum umdns_socket_type type)
                break;
        }
 
+retry:
        if (type & SOCKTYPE_BIT_IPV6) {
                ufd[type].cb = read_socket6;
                if (bind(fd, (struct sockaddr *)&local6, sizeof(local6)) < 0)
@@ -545,6 +544,14 @@ static int interface_init_socket(enum umdns_socket_type type)
        return 0;
 
 error:
+       if (!reuseport) {
+#ifdef SO_REUSEPORT
+               setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &yes, sizeof(yes));
+#endif
+               reuseport = true;
+               *mcast = true;
+               goto retry;
+       }
        close(ufd[type].fd);
        return -1;
 }
@@ -555,9 +562,10 @@ __interface_add(const char *name, enum umdns_socket_type type,
 {
        struct interface *iface;
        unsigned int ifindex;
+       bool mcast = false;
        char *id_buf;
 
-       if (interface_init_socket(type))
+       if (interface_init_socket(type, &mcast))
                goto error;
 
        ifindex = if_nametoindex(name);
@@ -572,6 +580,7 @@ __interface_add(const char *name, enum umdns_socket_type type,
        iface->ifindex = ifindex;
        iface->type = type;
        iface->addrs = *list;
+       iface->need_multicast = mcast;
 
        vlist_add(&interfaces, &iface->node, id_buf);
        return;
index aca2f41a31fe1d663ebe64ec8eb83a734bfa6d68..0c37736aee4d871e1bab2f97d9bf799133d586c3 100644 (file)
@@ -52,6 +52,7 @@ struct interface {
 
        const char *name;
        enum umdns_socket_type type;
+       bool need_multicast;
        int ifindex;
 
        struct interface_addr_list addrs;